package common.project.epic.ui;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class TouchGeoSpan extends Activity implements OnTouchListener {

	public static final String TAG = "Epic: ToucGeoSpan Activity";
    public static final boolean DEBUG = EpicDebugUI.DEBUG;
	
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    
//    private ImageView span_view;
    
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    
    private int touch_mode = NONE;
    
 // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;
    
    @Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    setContentView(R.layout.touchgeospan);
	    if(DEBUG) {
    		Log.d(TAG, "onCreate()");
    	}
	    ImageView span_view = (ImageView)findViewById(R.id.geo_span_image);
	    
	    
	    int span_view_width = span_view.getWidth();
	    int span_view_height = span_view.getHeight();
	    matrix.postTranslate(span_view_width/2, span_view_height/2);
	    
	    if(DEBUG) {
    		Log.d(TAG, "getWidth()=" + span_view_width + " getHeight()=" + span_view_height);
    	}
	    
	    span_view.setOnTouchListener(this);
	    matrix.set(savedMatrix);
//		matrix.postTranslate(160,360);
	}
    
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    	ImageView view = (ImageView)v;
    	
    	if(DEBUG) {
    		// dump touch event to log
        	dumpEvent(event);
    	}
    	
    	// handle touch event
    	switch(event.getAction() & MotionEvent.ACTION_MASK) {
    		case(MotionEvent.ACTION_DOWN): {
    			if(DEBUG) {
    				Log.d(TAG, "mode=DRAG");
    			}
    			savedMatrix.set(matrix);
    			start.set(event.getX(), event.getY());
    			touch_mode = DRAG;
    			break;
    		}
    		case(MotionEvent.ACTION_UP): {
    			
    		}
    		case(MotionEvent.ACTION_POINTER_UP): {
    			if(DEBUG) {
    				Log.d(TAG, "mode=NONE");
    			}
    			touch_mode = NONE;
    			break;
    		}
    		case(MotionEvent.ACTION_MOVE): {
    			if(DEBUG) {
    				Log.d(TAG, "mode=DRAG");
    			}
    			if(touch_mode == DRAG) {
    				matrix.set(savedMatrix);
    				matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
    			}
    			else {
    				if(touch_mode == ZOOM) {
    					float newDist = spacing(event);
    					if(newDist>10f) {
    						matrix.set(savedMatrix);
    						float scale = newDist/oldDist;
    						matrix.postScale(scale, scale, mid.x, mid.y);
    						if(DEBUG) {
            					Log.d(TAG, "newDist=" + newDist);
            				}
    					}
    				}
    			}
    			break;
    		}
    		case(MotionEvent.ACTION_POINTER_DOWN): {
    			oldDist = spacing(event);
    			if(oldDist>10f) {
    				savedMatrix.set(matrix);
    				midPoint(mid,event);
    				if(DEBUG) {
    					Log.d(TAG, "mode=ZOOM");
    					Log.d(TAG, "oldDist=" + oldDist);
    				}
    				touch_mode = ZOOM;
    			}
    			break;
    		}
    	}
    	
    	// perform the transformaiton
    	view.setImageMatrix(matrix);
    	
    	// return TRUE indicates that event was handled
    	return true;
    }
    
    /** show an event in the Log file for debugging */
    private void dumpEvent(MotionEvent event) {
    	String names[] = {"DOWN","UP","MOVE","CANCEL","OUTSIDE","POINTER_DOWN","POINTER_UP","7nani","8biscotto","9provadel"};
    	StringBuilder str_b = new StringBuilder();
    	int action = event.getAction();
    	int actionCode = action & MotionEvent.ACTION_MASK;
    	str_b.append("event ACTION_").append(names[actionCode]);
    	if(actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) {
    		str_b.append("(pid ").append(action >> MotionEvent.ACTION_POINTER_INDEX_SHIFT).append(")");
    	}
    	str_b.append("[");
    	for(int i=0; i<event.getPointerCount(); i++) {
    		str_b.append("#").append(i).append("(pid ").append(event.getPointerId(i)).append(")=");
    		str_b.append((int)event.getX(i)).append(",").append((int)event.getY(i));
    		if(i+1<event.getPointerCount()) {
    			str_b.append(";");
    		}
    		str_b.append("]");
    		Log.d(TAG, str_b.toString());
    	}
    }
    
    private float spacing(MotionEvent event) {
    	float delta_x = event.getX(0) - event.getX(1);
    	float delta_y = event.getY(0) - event.getY(1);
    	return FloatMath.sqrt(delta_x*delta_x + delta_y*delta_y);
    }
    
    private void midPoint(PointF point, MotionEvent event) {
    	float mid_x = (event.getX(0) + event.getX(1))/2;
    	float mid_y = (event.getY(0) + event.getY(1))/2;
    	point.set(mid_x,mid_y);
    }
    
}
